<template>

  <div>
    <el-upload
      class="upload-demo"
      action="/"
      :on-preview="handlePreview"
      :on-remove="handleRemove"
      :before-remove="beforeRemove"
      :before-upload="beforeUpload"
      multiple
      :limit="3"
      :on-exceed="handleExceed"
      :file-list="fileList">
      <el-button size="small" type="primary">点击上传</el-button>
      <div slot="tip" class="el-upload__tip">只能上传jpg/png文件，且不超过500kb</div>
    </el-upload>
  </div>
</template>

<script>


import axios from "axios";
import SparkMD5 from 'spark-md5'; // 导入 SparkMD5 库
export default {
  data() {
    return {
       CHUNK_SIZE : 5 * 1024 * 1024,
       uploadedChunks:[],
       md5:''
    }
  },
  name: 'App',
  components: {
  },
  methods: {
    handleRemove(file, fileList) {
      console.log(file, fileList);
    },
    handlePreview(file) {
      console.log(file);
    },
    handleExceed(files, fileList) {
      this.$message.warning(`当前限制选择 3 个文件，本次选择了 ${files.length} 个文件，共选择了 ${files.length + fileList.length} 个文件`);
    },
    beforeRemove(file, fileList) {
      return this.$confirm(`确定移除 ${ file.name }？`);
    },

    getFileChunks(file){
      let CHUNK_SIZE = this.CHUNK_SIZE;
      const chunkCount = Math.ceil(file.size / CHUNK_SIZE);
      const chunks = [];
      for (let i = 0; i < chunkCount; i++) {
        const start = i * CHUNK_SIZE;
        const end = Math.min(file.size, start + CHUNK_SIZE);
        chunks.push(file.slice(start, end));
      }

      return chunks;
    },

    beforeUpload(file, fileList){

       if (file.size<1024*1024*100){
         // 执行上传...
         this.getFileMd5(file).then((md5)=>{
           this.$http.post('/res/file/init?fileName=' + file.name+'&fileMd5='+md5, {
             fileName: file.name,
             fileMd5: md5 // 文件MD5计算
           }).then(res=>{
             let uploadId= res.data.data;

             // 2. 分块上传
             const chunks = this.getFileChunks(file);
             const total = chunks.length;
             let uploaded = 0;

             Promise.all(chunks.map((chunk, index) => {
               const formData = new FormData();
               formData.append('chunk', chunk, `chunk_${index}`);
               formData.append('index', index);
               formData.append('uploadId', uploadId);
               formData.append('fileMd5', md5);

               return axios.post('/res/file/chunk', formData, {
                 headers: {'Content-Type': 'multipart/form-data'},
                 onUploadProgress: progress => {
                   // 更新进度条
                   const percent = ((uploaded * 100) / total).toFixed(1);
                   console.log('----------percent----------------',percent)
                 }
               }).then(() => uploaded++);
             })).then(res=>{
               // 3. 触发合并
               axios.post('/res/file/merge?fileName=' + file.name+"&uploadId=" + uploadId+'&fileMd5='+md5, {
                 fileName: file.name,
                 uploadId,
                 md5
               });
             });
           }).catch(err=>{
             this.$router.push({path:'/login',query:{}});
             console.log(err)
           });

           console.log('-resres-----',res);
         });
       }else{
         this.calculateMD5(file).then((res)=>{
           alert(this.md5)
           alert(res)
         });

       }







      // let uploadedChunks = this.uploadedChunks;
      // chunks.map((chunk, index) => {
      //   if (uploadedChunks.includes(index)) {
      //
      //   }
      //
      // });

    },
    readFile(chunk, fileReader) {
      return new Promise((resolve, reject) => {
        fileReader.onload = (e) => {
          resolve(e.target.result);
        };
        fileReader.onerror = reject;
        fileReader.readAsArrayBuffer(chunk);
      });
    }
  ,

    async calculateMD5(file) {
      const chunkSize = 1024 * 1024; // 分块大小为 1MB
      const spark = new SparkMD5.ArrayBuffer();
      const fileReader = new FileReader();
      const totalChunks = Math.ceil(file.size / chunkSize);
      let currentChunk = 0;

      while (currentChunk < totalChunks) {
        const start = currentChunk * chunkSize;
        const end = Math.min(start + chunkSize, file.size);
        const chunk = file.slice(start, end);

        // 异步读取文件块并计算 MD5
        const arrayBuffer = await this.readFile(chunk, fileReader);
        spark.append(arrayBuffer);
        currentChunk++;
      }

      // 获取最终的 MD5 值
      this.md5 = spark.end();
    },


  getFileMd5(file) {
      if (file.size()<1024*1024*100){
        return new Promise((resolve, reject) => {
          let fileReader = new FileReader()
          fileReader.readAsArrayBuffer(file)
          fileReader.onload = function (event) {
            let fileMd5 = SparkMD5.ArrayBuffer.hash(event.target.result)
            resolve(fileMd5)
          }
        })
      }else {
        this.calculateMD5(file);
      }

  },
    // async  getFileMd5(file){
    //   let fileReader = new FileReader();
    //   let Spark = new SparkMD5.ArrayBuffer();
    //   let md5;
    //   fileReader.readAsArrayBuffer(file);
    //    fileReader.onload = await function (e) {
    //     Spark.append(e.target.result);
    //      md5 = Spark.end();
    //      console.log(md5);
    //
    //   };
    //     return md5;
    // },


    async  getUploadedChunks(fileMd5,uploadId ){
      this.uploadedChunks = await axios.get(
        `/upload/check/${fileMd5}/${uploadId}`
      );
    },

    async init(file,fileMd5) {
      // 1. 初始化上传
      const { data: uploadId } = await this.$http.post('/upload/init', {
        fileName: file.name,
        fileMd5: fileMd5 // 文件MD5计算
      });

      // 2. 分块上传
      const chunks = this.getFileChunks(file);
      const total = chunks.length;
      let uploaded = 0;

      await Promise.all(chunks.map((chunk, index) => {
        const formData = new FormData();
        formData.append('chunk', chunk, `chunk_${index}`);
        formData.append('index', index);
        formData.append('uploadId', uploadId);
        formData.append('fileMd5', fileMd5);

        return axios.post('/upload/chunk', formData, {
          headers: {'Content-Type': 'multipart/form-data'},
          onUploadProgress: progress => {
            // 更新进度条
            const percent = ((uploaded * 100) / total).toFixed(1);
          }
        }).then(() => uploaded++);
      }));

      // 3. 触发合并
      const result = await axios.post('/upload/merge', {
        fileName: file.name,
        uploadId,
        fileMd5
      });

      alert(`上传成功: ${result.data}`);
    }



  }
}
</script>

<style >


</style>
